package com.turbo.cloud.core.security.config;


import com.alibaba.fastjson2.JSON;
import com.turbo.cloud.core.annotations.Anonymous;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.util.pattern.PathPattern;

import java.util.*;

/**
 * 设置Anonymous注解允许匿名访问的url
 *
 * @author srgktzjt
 */
@Slf4j
@Configuration
public class AnonymousUrlsConfig implements InitializingBean, ApplicationContextAware {
    private static final String REGEX = "\\{(.*?)\\}";
    private static final String ASTERISK = "*";

    private ApplicationContext applicationContext;

    /**
     * -- GETTER --
     * 获取匿名接口
     */
    @Getter
    private final List<String> urls = new ArrayList<>();

    @Override
    public void afterPropertiesSet() {
        Map<String, RequestMappingHandlerMapping> map = applicationContext.getBeansOfType(RequestMappingHandlerMapping.class);
        map.forEach((key, value) -> {
            //获取method
            Map<RequestMappingInfo, HandlerMethod> methodMap = value.getHandlerMethods();
            //获取methodMap的key集合
            for (RequestMappingInfo info : methodMap.keySet()) {
                // 获取方法上边的注解 替代path variable 为 *
                Anonymous method = AnnotationUtils.findAnnotation(methodMap.get(info).getMethod(), Anonymous.class);
                if (Objects.nonNull(method)) {
                    if (Objects.nonNull(info.getPathPatternsCondition()) && !CollectionUtils.isEmpty(info.getPathPatternsCondition().getPatterns())) {
                        Set<PathPattern> urlSet = info.getPathPatternsCondition().getPatterns();
                        urls.addAll(urlSet.stream().map(path -> path.getPatternString().replaceAll(REGEX, ASTERISK)).toList());
                    }
                }
            }
        });
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.applicationContext = context;
    }

}
